// bsp3.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const int LINE_LENGTH = 100;

struct Matrix;
Matrix* ReadMatrix (char*);
int IsMultiplicationPossible(Matrix*, Matrix*);
Matrix* Multiply(Matrix*, Matrix*);
void PrintMatrix(Matrix *matrix);
Matrix* CreateMatrix(int rows, int columns);

struct Matrix{
	int rows, columns;
	int **a;
};

int main(int argc, char* argv[])
{
	Matrix *matrix1 = ReadMatrix("matrix1.txt");
	PrintMatrix(matrix1);
	Matrix *matrix2 = ReadMatrix("matrix2.txt");
	PrintMatrix(matrix2);
	Matrix *matrix3 = ReadMatrix("matrix3.txt");
	PrintMatrix(matrix3);

	Matrix *matrix4 = Multiply(matrix1, matrix2);
	PrintMatrix(matrix4);
	getchar();
	return 0;
}

Matrix* ReadMatrix(char *filename)
{
	Matrix *matrix = new Matrix;
	//Open Matrix File
	FILE *fp = fopen(filename, "r");
	
	if(fp)
	{
		printf("Matrix file opened - ");
		int rows = 0, columns = 0;
		char *line = (char *)malloc(sizeof(char)*LINE_LENGTH);
		
		//get number of rows
		while(fgets(line, LINE_LENGTH, fp))rows++;
		rewind(fp);
		if(rows > 0)
		{
			//read first line again and and count blanks
			fgets(line, LINE_LENGTH, fp);
			char* blank = line;
			blank = strchr(line, ' ');
			while(blank)
			{
				columns++;
				blank = strchr(blank+1, ' ');
			}
			columns++;
			//create matrix with size rows x columns
			matrix = CreateMatrix(rows, columns);

			
			printf("Rows: %d, Columns: %d \n", rows, columns);
			rewind(fp);
			//read the file line by line and get matrix values
			rows = 0; columns = 0;
			while(fgets(line, LINE_LENGTH, fp))
			{
				blank = strchr(line, ' ');
				while(blank)
				{
					int d = blank - line;
					char *buf = (char*)malloc(sizeof(char)*d);
					for(int i = 0; i < d; i++)
					{
						*buf = *line;
						line++;
						buf++;
					} 
					buf -= d;
					int value = atoi(buf);
					//save value in matrix
					*(*(matrix->a+rows)+columns) = value;
					columns++;
					blank = strchr(line+1, ' ');
				}
				blank = strchr(line+1, '\0');
				int d = blank - line;
				char *buf = (char*)malloc(sizeof(char)*d);
				for(int i = 0; i < d; i++)
				{
					*buf = *line;
					line++;
					buf++;
				} 
				buf -= d;
				int value = atoi(buf);
				//save value in matrix
				*(*(matrix->a+rows)+columns) = value;
				columns = 0;
				rows++;
			}
		}
		fclose(fp);
	}
	return matrix;
}

void PrintMatrix(Matrix *matrix)
{
	if(matrix)
	{
		for(int i = 0; i < matrix->rows; i++)
		{
			for(int j = 0; j < matrix->columns; j++)
			{
				printf("%d ", matrix->a[i][j]);
			}
			printf("\n");
		}
	}
	
}

int IsMultiplicationPossible(Matrix *matrix1, Matrix *matrix2)
{
	if(matrix1->columns == matrix2->rows)return 1;
	else return 0;
}

Matrix* Multiply(Matrix *matrix1, Matrix *matrix2)
{
	Matrix *result = NULL;
	if(IsMultiplicationPossible(matrix1, matrix2))
	{
		result = CreateMatrix(matrix1->rows, matrix2->columns);
		
		for(int i = 0; i < result->rows; i++)
		{
			for(int j = 0; j < result->columns; j++)
			{
				*(*(result->a+i)+j) = 0;
				printf("result[%d][%d] = ", i, j);
				for(int x = 0; x < matrix1->columns; x++)
				{
					printf("%d * %d + ", *(*(matrix1->a+i)+x) , *(*(matrix2->a+x)+j));
					*(*(result->a+i)+j) += *(*(matrix1->a+i)+x) * *(*(matrix2->a+x)+j);
				}
				printf("\n");
			}
		}
	}
	return result;
}

Matrix* CreateMatrix(int rows, int columns)
{
	Matrix* result = new Matrix;
	result->rows = rows;
	result->columns = columns;
	//allocate memory for row pointers
	result->a = (int**)malloc(sizeof(int)*result->rows);

	//allocate memory for column pointers
	for(int i = 0; i < rows; i++)
	{
		*(result->a+i) = (int*)malloc(sizeof(int)*columns); 
	}
	return result;
}

